Polymorphic React Components
Componentの中のHTMLタグを多相にする
<Button as="a" />とすれば<button>ではなく<a>になる感じ
要件
指定されたタグのみ選択できる
e.g. "a" | "button"
指定されたタグの標準のpropsのみ受け入れる
e.g. "a"を指定した場合は、href=が使える
e.g. "button"を指定した場合は、href=が使えない
ユースケース
そんなに頑張らなくても、これで十分な気がしてきた
code:ts
type AProps = {
as: 'a';
href: string;
};
type ButtonProps = {
as: 'button';
onClick: () => void;
};
type Props = AProps | ButtonProps;
export const AddButton: React.FC<Props> = ({ as: Tag, ...props }) => {
return (
<Tag
className="bg-gray-400 hover:bg-gray-500 text-white font-bold py-2 px-4 rounded-full"
{...props}
+
</Tag>
);
};
この記事、結論おかしくないかmrsekut.icon
この定義だと、<Button tagName="button" href="..."/>もvalidになってしまう
要素の制限ができない
任意のタグを指定できてしまう
code:ts
export const ButtonDefaultAsType = 'button' as const
export type ButtonDefaultAsType = typeof ButtonDefaultAsType
export type ButtonOwnProps<E extends React.ElementType> = {
children: React.ReactNode
as?: E
}
export type ButtonProps<E extends React.ElementType> = ButtonOwnProps<E> &
Omit<React.ComponentProps<E>, keyof ButtonOwnProps<E>>
export const Button = <E extends React.ElementType = ButtonDefaultAsType>({
children,
as,
...otherProps
}: ButtonProps<E>) => {
const Tag = as || ButtonDefaultAsType
return <Tag {...otherProps}>{children}</Tag>
}